﻿using System;
using IoTClient.Clients.Modbus;
using ModbusCollect.entity;

namespace ModbusCollect.Services
{
    public class ModbusTcpService : IDisposable
    {

        private ModbusTcpClient? client;

        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public bool Connect(string ip, int port = 502)
        {
    
            client = new ModbusTcpClient(ip, port);
            client.Open();
            return client.Connected;
        }

        /// <summary>
        /// 关闭
        /// </summary>
        public void Disconnect()
        {
            client?.Close();
        }


        public void Dispose()
        {
            Disconnect();
        }

        /// <summary>
        /// 读取保持寄存器
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="address"></param>
        /// <param name="slaveId"></param>
        /// <param name="functionCode"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        /// <exception cref="NotSupportedException"></exception>
        /// <exception cref="Exception"></exception>
        public T ReadHoldingRegisters<T>(string address, byte slaveId = 1, byte functionCode = 3) where T : struct
        {

            Connect("127.0.0.1",502);
            if (client == null || !client.Connected)
                throw new InvalidOperationException("Modbus client未能建立连接");

            object? value = null;

            if (typeof(T) == typeof(short))
                value = client.ReadInt16(address, slaveId, functionCode)?.Value;
            else if (typeof(T) == typeof(ushort))
                value = client.ReadUInt16(address, slaveId, functionCode)?.Value;
            else if (typeof(T) == typeof(int))
                value = client.ReadInt32(address, slaveId, functionCode)?.Value;
            else if (typeof(T) == typeof(uint))
                value = client.ReadUInt32(address, slaveId, functionCode)?.Value;
            else if (typeof(T) == typeof(long))
                value = client.ReadInt64(address, slaveId, functionCode)?.Value;
            else if (typeof(T) == typeof(ulong))
                value = client.ReadUInt64(address, slaveId, functionCode)?.Value;
            else if (typeof(T) == typeof(float))
                value = client.ReadFloat(address, slaveId, functionCode)?.Value;
            else if (typeof(T) == typeof(double))
                value = client.ReadDouble(address, slaveId, functionCode)?.Value;
            else
                throw new NotSupportedException($"类型 {typeof(T)} 不支持");

            if (value == null)
                throw new Exception($"读取 {typeof(T)} 类型数据失败");

            return (T)value;
        }

        /// <summary>
        /// 写入保持寄存器
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <param name="slaveId"></param>
        /// <param name="functionCode"></param>
        /// <exception cref="InvalidOperationException"></exception>
        /// <exception cref="NotSupportedException"></exception>
        public void WriteRegister<T>(string address, string value, byte slaveId = 1, byte functionCode = 16) where T : struct
        {
            Connect("127.0.0.1", 502);
            if (client == null || !client.Connected)
                throw new InvalidOperationException("Modbus client未连接");

            if (typeof(T) == typeof(short))
                client.Write(address, short.Parse(value), slaveId, functionCode);
            else if (typeof(T) == typeof(ushort))
                client.Write(address, ushort.Parse(value), slaveId, functionCode);
            else if (typeof(T) == typeof(int))
                client.Write(address, int.Parse(value), slaveId, functionCode);
            else if (typeof(T) == typeof(uint))
                client.Write(address, uint.Parse(value), slaveId, functionCode);
            else if (typeof(T) == typeof(long))
                client.Write(address, long.Parse(value), slaveId, functionCode);
            else if (typeof(T) == typeof(ulong))
                client.Write(address, ulong.Parse(value), slaveId, functionCode);
            else if (typeof(T) == typeof(float))
                client.Write(address, float.Parse(value), slaveId, functionCode);
            else if (typeof(T) == typeof(double))
                client.Write(address, double.Parse(value), slaveId, functionCode);
            else
                throw new NotSupportedException($"类型 {typeof(T)} 不支持写入");
        }


    }
}
